package samples.stream;

import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import samples.lambda.Person2;

import java.util.*;
import java.util.stream.Collectors;

public class CollectorsTest {

    private List<Person2> list;
    private List<String> strings;

    // 初始化数据需要的
    @Before
    public void inti() {
        Person2 p1 = new Person2(13, "男", "张2");
        Person2 p2 = new Person2(2, "男", "张6");
        Person2 p3 = new Person2(4, "男", "张1");
        Person2 p4 = new Person2(6, "女", "张3");
        Person2 p5 = new Person2(1, "男", "张5");
        Person2 p6 = new Person2(10, "男", "张8");
        Person2 p7 = new Person2(3, "女", "张4");
        Person2 p8 = new Person2(31, "女", "张4");
        Person2 p9 = new Person2(21, "女", "张4");
        Person2 p10 = new Person2(19, "女", "张4");

        list = Lists.newArrayList(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
        strings = Lists.newArrayList("a1", "a2", "b1", "c2", "c1");
    }


    /**
     * list 2分组
     * partitioningBy
     * 根据相关条件分两组
     * True /False（等于2/不等于2）
     */
    @Test
    public void t1() {
        Map<Boolean, List<Person2>> collect = list.stream().collect(Collectors.partitioningBy(e -> e.getId().equals(2)));
        System.out.println(collect.toString());
    }

    /**
     * {false=[], true=[13, 2, 4, 6, 1, 10, 3, 31, 21, 19]}
     */
    @Test
    public void t2() {
        ArrayList<Integer> ids = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);
        Map<Boolean, List<Integer>> collect = list.stream().map(Person2::getId)
                .collect(Collectors.partitioningBy(e -> ids.stream().allMatch(ids::contains)));
        int tsize = collect.get(Boolean.TRUE).size();
        int fsize = collect.get(Boolean.FALSE).size();
        System.out.printf("True:%d ; false:%d", tsize, fsize);
    }

    /**
     * {false=[], true=[13, 2, 4, 6, 1, 10, 3, 31, 21, 19]}
     */
    @Test
    public void t2_1() {
        ArrayList<Integer> ids = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);
        Map<Boolean, List<Integer>> collect = list.stream().map(Person2::getId)
                .collect(Collectors.partitioningBy(e -> ids.stream().anyMatch(ids::contains)));
        System.out.println(collect.toString());
    }

    /**
     * 分两组，在已知集合或不在的
     * {false=[Person2(id=13, sex=男, lastName=张2), Person2(id=10, sex=男, lastName=张8), Person2(id=31, sex=女, lastName=张4), Person2(id=21, sex=女, lastName=张4), Person2(id=19, sex=女, lastName=张4)],
     * true=[Person2(id=2, sex=男, lastName=张6), Person2(id=4, sex=男, lastName=张1), Person2(id=6, sex=女, lastName=张3), Person2(id=1, sex=男, lastName=张5), Person2(id=3, sex=女, lastName=张4)]}
     */
    @Test
    public void t3() {
        ArrayList<Integer> ids = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);
        Map<Boolean, List<Person2>> collect = list.stream()
                .collect(Collectors.partitioningBy(e -> ids.contains(e.getId())));
        System.out.println(collect.toString());
    }

    /**
     * singleton 测试
     * List1 value: [Two, Three, Two, Three]
     * The SingletonList is :[Two, Three, Two, Three]
     */
    @Test
    public void t4() {
        // create an array of string objs
        String init[] = {"One", "Two", "Three", "One", "Two", "Three"};

        // create two lists
        List list1 = new ArrayList(Arrays.asList(init));
        List list2 = new ArrayList(Arrays.asList(init));

        // remove from list1
//        list1.remove("One");
        list1.removeAll(Lists.newArrayList("One"));
        System.out.println("List1 value: " + list1);

        // remove from list2 using singleton
        list2.removeAll(Collections.singleton("One"));
        System.out.println("The SingletonList is :" + list2);
    }

    @Test
    public void t4_1() {
        Map<String, List<Person2>> users = Collections.singletonMap("users", list);
        System.out.println("The singletonMap is :" + users);
    }


    /**
     * List 根据长度分组
     * 1 words with 1 chars
     * 3 words with 3 chars
     * 3 words with 4 chars
     * 2 words with 5 chars
     * 1 words with 7 chars
     */
    @Test
    public void t31() {
        ArrayList<String> strings = Lists.newArrayList("tasq", "tsa", "taptd", "t", "ta", "tasqd", "tsar", "tapwetd", "tyt", "taqw");
        mappingWordsLength(strings);
    }

    private void mappingWordsLength(List<String> wordsList) {
        Map<Integer, Set<String>> mapping = new HashMap<>();
        for (String word : wordsList) {
            mapping.computeIfAbsent(word.length(), HashSet::new).add(word);
        }
        List<Integer> lengths = new LinkedList<>(mapping.keySet());
        Collections.sort(lengths);
        lengths.forEach(n -> System.out.println(mapping.get(n).size() + " words with " + n + " chars"));
    }


}
